import { BoidArmor, BoidStatus, BoidBuff, BoidType } from "../../config/boid_def";
import { CollisionTag, GetBuffType, MAX_SPEED, BOID_DEBUT_TIME,DEFAULT_ATTACKSPEED,MIN_ATTACKSPEED } from "../../config/play_def";
import { Control_Listen } from "../../config/ui_def";

cc.Class({
    extends: cc.Component,

    properties: {
        orderId: 0,              // 单位编号
        _speed: {
            visible: false,
            default: 100,
        },                      // 基础移动
        speed: {
            visible: false,
            get() {
                let sec // 之前为帧所以为秒。现在为倍数
                // let speed = 2
                let speed = this._speed - (this._speed * this.getBuff(BoidBuff.Slow) / 100) + (this._speed * this.getBuff(BoidBuff.Accelerate) / 100)
                if (speed > MAX_SPEED) {
                    sec = 4
                } else {
                    sec = speed / 100
                }
                // 400是这段路用 0.25s 100是这段路用 1s
                // 速度值变量为每秒移动的距离（之前为每帧

                if (window.gg && gg.boidsManager) {
                    return gg.boidsManager.way_size.height * sec
                } else {
                    return 100 * sec
                }
            }
        },                      // 整体移动速度
        _attackSpeed:{
            visible: false,
            default: 100,
        },                      // 
        attackSpeed:{
            visible: false,
            get() {
                let sec // 之前为帧所以为秒。现在为倍数
                // let speed = 2
                let speed = DEFAULT_ATTACKSPEED / (this._attackSpeed / DEFAULT_ATTACKSPEED)
                
                if (speed > MIN_ATTACKSPEED) {
                    sec = 10
                } else {
                    sec = speed / 100
                }
                return sec
            }
        },
        backLimit: {
            visible: false,
            default: 0
        },                      // 击退上限每秒
        backDis: {
            visible: false,
            default: 0
        },                      // 需要击退的距离
        backSecCount: {
            visible: false,
            default: 0
        },                      // 每秒击退记录
        backSecDtCount: {
            visible: false,
            default: 0
        },                      // 击退时间记录
        buff_content: cc.Node,
        status: {
            type: cc.Enum(BoidStatus),
            default: BoidStatus.Load
        },                      // 状态
        collision: cc.PolygonCollider,// 盒碰撞
        move: false,             // 是否能移动
        Hp_node: cc.Node,        // 血条节点
        Hp_bar: cc.Sprite,       // 血条
        HP: {                   // 血量值
            visible: false,
            default: 100,
        },
        Hp_max: {               // 血量上限
            visible: false,
            default: 100,
        },
        HP_value: {              // 当前动画值
            visible: false,
            default: 100,
        },
        type: {
            visible: false,
            type: cc.Enum(BoidType),
            default: BoidType.MOBS
        },
        armor: {
            visible: false,
            type: cc.Enum(BoidArmor),
            default: BoidArmor.None
        },                      // 护甲类型
        damege: 1,              // 碰撞伤害
        hitnum: 0,              // 被击打数
        fly: false,             // 是否飞行单位
        timeSave: [],           // 时间戳记录
        miss: 0,                // 攻击丢失概率
        range: 0,               // 射程
        melee: false,           // 是否发射子弹
    },
    initInfo(param, order) {
        this.move = false
        this.order_line = order + 1             // 当前列
        this.status = BoidStatus.Load           // 加载中
        this.buffDict = {}                      // buff 初始化
        this.buff = []                          // buff 列表
        this.buffAni = {}                       // buff动画
        this.hitnum = 0                         // 打击数归零
        this.Hp_bar.fillRange = 1               // 血条初始化
        this.miss = 0                           // 丢失率
        this.range = 0                          // 攻击范围
        this.attackDtCount = 0                  // 攻击计数


        this.clearBuffAni()
        // this.node.on(cc.Node.EventType.TOUCH_START, this.clickStart, this)
        // this.node.on(cc.Node.EventType.TOUCH_END, this.clickOver, this)
    },
    clearInfo(delNode) {
        this.status = BoidStatus.Dead           // 单位阵亡
        this.order_line = 0
        this.buffDict = {}                      // buff初始化
        this.buff = []
        this.miss = 0
        this.back = 0                           // 击退数归零
        this.fly = false                        // 默认不为分型单位
        this.collision.enabled = false          // 碰撞取消
        this.Hp_node.active = false             // 血条隐藏
        this.timeSave = []                      // 清除点击事件
        this.node.opacity = 255                 // 透明度回归
        this.backDis = 0                        // 击退距离
        this.backLimit = 0                      // 每秒击退值
        this.backSecCount = 0                   // 每秒击退距离记录
        this.backSecDtCount = 0                 // 击退时间记录
        // this.node.off(cc.Node.EventType.TOUCH_START, this.clickStart, this)
        // this.node.off(cc.Node.EventType.TOUCH_END, this.clickOver, this)
        for (let ani in this.buffAni) {
            this.buffAni[ani].clearInfo()
        }
        this.buffAni = {}                       // buff动画
        this.orderId = 0
        gg.boidsManager.delBoid(this.orderId)      // 删除该单位
        if (delNode) {                            // 单位入池
            he.pool.putElement("monster", this.node)
        }
    },
    // 阵亡 
    // 直接消失到单位部分基本需要复写
    Dead() {
        this.deadSkill()
        this.clearInfo(true)
    },
    clearBuffAni(){
      if(this.buff_content && this.buff_content.childrenCount){
        let delnum = this.buff_content.childrenCount
        for(let i = delnum - 1; i >= 0;i--){
          let buffScript = this.buff_content.children[i].getComponent('buffAni')
          if(buffScript){
            buffScript.clearInfo()
          }
        } 
      }
    },
    canAttack() {
        switch (this.status) {
            case BoidStatus.Live:
            case BoidStatus.Attack:
            case BoidStatus.Playing:
                return true
        }
        return false
    },
    moveAction(dt) {
        switch (this.status) {
            case BoidStatus.Live:   // 存活中
                let moveRes = this.node.y
                let back = 0
                if (this.backDis > 0) {
                    this.backSecDtCount += dt
                    back = this.backLimit * dt
                    if (this.backSecCount + back > this.backLimit) {
                        back = 0
                    } else {
                        this.backSecCount += back
                        this.backDis -= back
                        if (this.backDis < 0) {
                            this.backDis = 0
                            this.backLimit = 0
                            back = 0
                            let zindex = gg.boidsManager.checkZindex(this.orderId, this.node.y, this.order_line)
                            if (zindex > 0) {
                                this.node.zIndex = zindex
                            }
                        }
                    }
                    if (this.backSecDtCount > 1) {
                        this.backSecCount = 0
                        this.backSecDtCount = 0
                    }
                }
                moveRes -= this.speed * dt - back
                if (this.range > moveRes + gg.boidsManager.way_node.height) {
                    moveRes = -gg.boidsManager.way_node.height + this.range
                    this.status = BoidStatus.Attack
                    this.standAni()
                }
                this.node.y = moveRes
                break
            case BoidStatus.Attack:
                if (this.backDis > 0) {
                    this.backSecDtCount += dt
                    let back = this.backLimit * dt * 5
                    if (this.backSecCount + back > this.backLimit) {
                        back = 0
                    } else {
                        this.backSecCount += back
                        this.backDis -= back
                        if (this.backDis < 0) {
                            this.backDis = 0
                            this.backLimit = 0
                            back = 0
                            let zindex = gg.boidsManager.checkZindex(this.orderId, this.node.y, this.order_line)
                            if (zindex > 0) {
                                this.node.zIndex = zindex
                            }
                        }
                    }
                    if (this.backSecDtCount > 1) {
                        this.backSecCount = 0
                        this.backSecDtCount = 0
                    }
                    this.node.y -= back
                    this.status = BoidStatus.Live
                }
                this.attackDtCount += dt
                if(this.attackDtCount > this.attackSpeed){
                    this.attackDtCount = 0
                    this.status = BoidStatus.Playing
                    this.attackAni()
                }
                break
            case BoidStatus.Playing:
                if (this.backDis > 0) {
                    this.backSecDtCount += dt
                    let back = this.backLimit * dt * 5
                    if (this.backSecCount + back > this.backLimit) {
                        back = 0
                    } else {
                        this.backSecCount += back
                        this.backDis -= back
                        if (this.backDis < 0) {
                            this.backDis = 0
                            this.backLimit = 0
                            back = 0
                            let zindex = gg.boidsManager.checkZindex(this.orderId, this.node.y, this.order_line)
                            if (zindex > 0) {
                                this.node.zIndex = zindex
                            }
                        }
                    }
                    if (this.backSecDtCount > 1) {
                        this.backSecCount = 0
                        this.backSecDtCount = 0
                    }
                    this.node.y -= back
                    this.status = BoidStatus.Live
                }
                break
            
        }
    },
    // 插入 登场动画 
    debutAni() {
        // 后期会随表更改动画类型
        let effect = {
            pos: this.getWorldPos(),
            pool: 'smoke',
            prefab: 'effect/smoke',
            script: 'smoke',
        }
        gg.bulletManager.addTopEffect(effect)
    },
    // 添加Buff
    addBuff(param) {
        if (param) {
            if (param.uid) {
                for (let i = 0; i < this.buff.length; i++) {
                    if (this.buff[i].uid == param.uid) {
                        this.buff[i] = param
                        return this.updateBuff(param.key)
                    }
                }
                this.buff.push(param)
                return this.updateBuff(param.key)
            } else {
                this.buff.push(param)
                return this.updateBuff(param.key)
            }
        }
    },
    // 获取Buff 统计值
    getBuff(key) {
        if (this.buffDict && (this.buffDict[key] || this.buffDict[key] === 0)) {
            return this.buffDict[key]
        } else {
            return this.updateBuff(key)
        }
    },
    // 获取Buff信息
    getBuffInfo(index, type, param) {
        switch (type) {
            case GetBuffType.INDEX:
                if (this.buff[index]) {
                    return this.buff[index]
                }
            case GetBuffType.UID:
                for (let i = 0; i < this.buff.length; i++) {
                    if (this.buff[i].uid == index) {
                        return this.buff[i]
                    }
                }
                break
            case GetBuffType.KAU:
                for (let i = 0; i < this.buff.length; i++) {
                    if (this.buff[i].uid == index && this.buff[i].key == param) {
                        return this.buff[i]
                    }
                }
                break
            case GetBuffType.KEY:
            default:
                for (let i = 0; i < this.buff.length; i++) {
                    if (this.buff[i].key == index) {
                        return this.buff[i]
                    }
                }
                break
        }
        return null
    },
    // 获得并删除
    getDelBuffInfo(id, type) {
        if (!type) {
            type = 1
        }
        let res = null
        switch (type) {
            case GetBuffType.INDEX:
                res = this.buff.splice(id, id + 1)
                this.buff.splice(id, 1)
                break
            case GetBuffType.UID:
                for (let i = 0; i < this.buff.length; i++) {
                    let buff = this.buff[i]
                    if (buff.uid && buff.uid == id) {
                        res = this.buff.splice(i, i + 1)
                        this.buff.splice(i, 1)
                        break
                    }
                }
                break
            case GetBuffType.KEY:
                for (let i = 0; i < this.buff.length; i++) {
                    let buff = this.buff[i]
                    if (buff.key && buff.key == id) {
                        res = this.buff.splice(i, i + 1)
                        this.buff.splice(i, 1)
                        break
                    }
                }
                break
        }
        this.updateBuff()
        if (res) {
            return res[0]
        }
        return res
    },
    // 获取同种类型Buff类型
    getBuffList(key) {
        let list = []
        for (let i = 0; i < this.buff.length; i++) {
            if (this.buff[i].key == key) {
                list.push(this.buff[i])
            }
        }
        return list
    },
    // 删除Buff
    delBuff(id, type) {
        // type 1 index, type 2 uid , type3 key
        // 索引，唯一，类型
        if (!type) {
            type = 1
        }
        switch (type) {
            case 1:
                this.buff.splice(id, 1)
                break
            case 2:
                for (let i = 0; i < this.buff.length; i++) {
                    let buff = this.buff[i]
                    if (buff.uid && buff.uid == id) {
                        this.buff.splice(i, 1)
                        break
                    }
                }
                break
            case 3:
                for (let i = this.buff.length - 1; i >= 0; i--) {
                    let buff = this.buff[i]
                    if (buff.key && buff.key == id) {
                        this.buff.splice(i, 1)
                        break
                    }
                }
                break
        }
        this.updateBuff()
    },
    // 更新Buff
    updateBuff(key) {
        if (!this.buff) {
            return
        }
        
        if (key) {
            let count = 0
            for (let i = 0; i < this.buff.length; i++) {
                if (this.buff[i].key == key) {
                    count += this.buff[i].value
                }
            }
            this.buffDict[key] = count
            if (key && this.buffDict) {
                if (this.buffDict[key] === undefined) {
                    this.buffDict[key] = 0
                    return 0
                }
                return this.buffDict[key]
            }
            return 0
        } else {
            let buffDict = {}
            for (let key in this.buffDict) {
                buffDict[key] = 0
            }
            for (let i = 0; i < this.buff.length; i++) {
                if (buffDict[this.buff[i].key]) {
                    buffDict[this.buff[i].key] += this.buff[i].value
                } else {
                    buffDict[this.buff[i].key] = this.buff[i].value
                }
            }
            this.buffDict = buffDict
            return 0
        }
    },
    // Buff清空后
    overBuff(buff) {
        this.updateBuff(buff.key)
        switch (buff.key) {
            case BoidBuff.DOT:
                let res = buff.overtime - buff.interval
                if (res > 0) {
                    buff.overtime = res
                    buff.time = buff.interval
                    this.addBuff(buff)
                }
                let damege = buff.count * buff.value
                this.hpHurt(buff.uid, damege, true)
                if (buff.ani) {
                    this.addBuffAni(buff.ani)
                    he.error("播放buff动画", buff.ani,buff.time)
                }
                break
            case BoidBuff.Stun:
                this.node.zIndex = gg.boidsManager.checkZindex(this.orderId, this.node.y, this.order_line)
            case BoidBuff.Hide:
                this.node.opacity = 255
                if (this.canAttack()) {
                    this.collision.enabled = true
                }
                break
        }
    },
    // 帧检测Buff
    checkBuff(dt) {
        if (this.buff && this.buff.length) {
            let buffList = []
            for (let i = this.buff.length - 1; i >= 0; i--) {
                if (this.buff[i].time > 0) {
                    this.buff[i].time -= dt
                }
                if (this.buff[i].time <= 0) {
                  buffList.push(this.buff[i])
                  this.buff.splice(i, 1)
                }
            }
            if (buffList && buffList.length) {
                for (let i = 0; i < buffList.length; i++) {
                    this.overBuff(buffList[i])
                }
            }
        }
    },
    // 生命值扣除
    hpHurt(from, v, noani) {
        if (!this.canAttack()) {
            return
        }
        this.hitnum += 1
        if (this.hitnum == 1) {
            this.firstSkill()
        }
        if (!v) {
            return
        }
        this.Hp_node.active = true
        let res = this.HP - v

        if (res > 0) {
            gg.data.saveDamege(from, v)
            this.HP = res
            if (!noani) {
                this.hurtAni()
            }
        } else {
            gg.data.saveDamege(from, this.HP)
            this.HP = 0
            if (!noani) {
                this.hurtAni()
            }
            if (this.info) {
                gg.data.saveHitDeath(from, this.info.monsterId || this.info.bossId)
                gg.data.saveDeathClass(this.info.monsterId)
            }
            if (this.status != BoidStatus.Dead) {
                this.Dead()
            }
        }
    },
    // 击退
    hitBack(v, limit) {
        if (!this.canAttack()) {
            return
        }
        this.backDis += v
        if (limit > this.backLimit) {
            this.backLimit = limit
        }
    },
    // 世界坐标
    getWorldPos() {
        let worldPos = this.model.node.convertToWorldSpaceAR(cc.Vec2.ZERO)
        return cc.v2(parseInt(worldPos.x), parseInt(worldPos.y))
    },
    hpAni() {
        // 当前血量不等于真实血量
        if (this.HP_value != this.HP) {
            let subValue = Math.ceil((this.HP_value - this.HP) / 5)
            this.HP_value -= subValue
            this.Hp_bar.fillRange = this.HP_value / this.Hp_max
        }
    },
    // 添加buff动画
    addBuffAni(ani,skin) {
        if(!this.canAttack()){
          return
        }
        if (this.buffAni[ani]) {
            this.buffAni[ani].play()
        } else {
            let buffNode = he.pool.getElement('buffAni')
            this.buffAni[ani] = buffNode.getComponent('buffAni')
            this.buffAni[ani].initInfo(ani,skin)
            this.buff_content.addChild(buffNode)
        }
    },
    // 按钮开始
    clickStart() {
        let timeNow = new Date().getTime()
        if (this.timeSave && this.timeSave.length && (timeNow - this.timeSave[0]) > common.DOUBLE_CLICK_OFFTIME) {
            this.timeSave = []
        }
        this.timeSave.push(timeNow)
    },
    // 按钮结束
    clickOver() {
        if (!this.canAttack()) {
            return
        }
        if (this.timeSave.length >= 2) {
            this.timeSave = []
        }
    },
    // 受伤动画
    hurtAni() {},
    // 第一击触发技能
    firstSkill() {},
    // 阵亡技能
    deadSkill() {},
    // 攻击技能
    attackSkill() {
        if (this.info && this.info.skill) {
            let skill_list = this.info.skill.split("#")
            let skill_param_list
            if (this.info.skillParam)
                skill_param_list = this.info.skillParam.split("#")
            for (let i = 0; i < skill_list.length; i++) {
                let skill_param
                if (skill_param_list)
                    skill_param = skill_param_list[i]
                switch (parseInt(skill_list[i])) {
                }
            }
        }
    },
    // 攻击动画
    attackAni(){},
    // 战力
    standAni(){},
    // 攻击效果
    attack() {
        this.attackSkill()
        gg.data.hurtHp(this.damege)
        this.status = BoidStatus.Attack // 演示完后就进行蓄力 此部分放在 攻击动画后
    },
    update(dt) {
        if (!gg.data.pause && this.move && gg.data.status) {
            this.checkBuff(dt)
            this.moveAction(dt)
            this.hpAni()
        }
    }
});
